﻿using EasyNet.Componets.Core.Logger;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace EasyNet.Componets.Logger
{
    public class NLogLogger : ILog
    {
        private ThreadLocal<Dictionary<Type, ILogger>> _threadLocalLogger;

        public NLogLogger()
        {

            _threadLocalLogger = new ThreadLocal<Dictionary<Type, ILogger>>
            {
                Value = new Dictionary<Type, ILogger>()
            };
        }

        private ThreadLocal<Dictionary<Type, ILogger>> ThreadLocalLogger
        {
            get
            {
                if (_threadLocalLogger == null)
                {
                    _threadLocalLogger = new ThreadLocal<Dictionary<Type, ILogger>>
                    {
                        Value = new Dictionary<Type, ILogger>()
                    };
                }

                if (_threadLocalLogger.Value == null) _threadLocalLogger.Value = new Dictionary<Type, ILogger>();

                return _threadLocalLogger;
            }
        }

        private ILogger GetLogger(Type type)
        {
            if (!ThreadLocalLogger.Value.ContainsKey(type))
            {
                ThreadLocalLogger.Value.Add(type, LogManager.GetLogger(type.FullName));
            }
            return ThreadLocalLogger.Value[type];
        }

        public void Debug(Type type, string message,
             string memberName = "",
             string sourceFilePath = "",
             int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                GetLogger(type).Debug(FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }



        public void Debug(Type type, string message, Exception exception,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {

                GetLogger(type).Debug(exception, FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void Debug(Type type, object item,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (item != null)
            {
                GetLogger(type).Debug(FormatMessage(item.ToString(), memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void LogInfo(Type type, string message,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                GetLogger(type).Info(FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void LogWarning(Type type, string message,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                GetLogger(type).Warn(FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void LogError(Type type, string message,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                GetLogger(type).Error(FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void LogError(Type type, string message, Exception exception,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message)
                &&
                exception != null)
            {
                GetLogger(type).Error(exception, FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void LogError(Type type, Exception exception,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (exception != null)
            {
                GetLogger(type).Error(exception, FormatMessage("", memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void Fatal(Type type, string message,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {

                GetLogger(type).Fatal(FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        public void Fatal(Type type, string message, Exception exception,
            string memberName = "",
            string sourceFilePath = "",
            int sourceLineNumber = 0)
        {
            if (!String.IsNullOrWhiteSpace(message)
                &&
                exception != null)
            {

                GetLogger(type).Fatal(exception, FormatMessage(message, memberName, sourceFilePath, sourceLineNumber));
            }
        }

        private string FormatMessage(string message, string memberName, string sourceFilePath, int sourceLineNumber)
        {
            return string.Format(
                "Method: {0}  File: {1} line:{2} Msg: {3}",
                memberName, sourceFilePath, sourceLineNumber, message);
        }
    }
}
